/** \file SingletonMgr.cc
 * Definitions for the class SingletonMgr.
 *
 * (c) Copyright 2003-2006 by Semih Cemiloglu
 * All rights reserved, see COPYRIGHT file for details.
 *
 * $Id: SingletonMgr.cc 119 2006-06-21 04:57:25Z semihc $
 *
 *
 */


#include "SingletonMgr.hh"
#include <algorithm>
#include <QThreadStorage>
#include "DBC.hpp"
#include "Throw.hh"

using namespace std;
using namespace TC;


TC_IDENT("$Id$");



//
// SingletonMgr
//

SingletonMgr::SingletonMgr()
{
  // Make a sensible reservation
  m_singletons.reserve(64); 
}

SingletonMgr::~SingletonMgr()
{
  try {
    destroyAllSingletons();
  }
  catch(...) {
  }
}


bool SingletonMgr::destroySingleton(TypeInfo ti)
{
  SingletonCol_t::iterator i = findSingleton(ti);
  if(i != m_singletons.end()) {
    // Remove the singleton holder
    m_singletons.erase(i);
    return true;
  }
  else
    return false;
}


unsigned SingletonMgr::getLongevity(TypeInfo ti)
{
  unsigned lgv = 0;
  SingletonCol_t::iterator i = findSingleton(ti);
  if(i != m_singletons.end())
    lgv = i->m_longevity;
  return lgv;
}


void SingletonMgr::setLongevity(TypeInfo ti, unsigned lgv)
{
  SingletonCol_t::iterator i = findSingleton(ti);
  if(i != m_singletons.end())
    i->m_longevity = lgv;
}


void SingletonMgr::destroyAllSingletons()
{
  sortSingletonsByLongevity();
  SingletonCol_t::iterator i = m_singletons.begin();
  for(; i!=m_singletons.end(); ++i)
    if(i->m_instance) {
      delete i->m_instance;
      i->m_instance = 0;
    }
}



SingletonMgr::SingletonCol_t::iterator 
SingletonMgr::findSingleton(TypeInfo ti)
{
  SingletonCol_t::iterator i = m_singletons.begin();

  for(; i!=m_singletons.end(); ++i) {
    if(ti == i->m_type)
      break;
  }

  return i;
}


void SingletonMgr::sortSingletonsByLongevity()
{
  std::stable_sort(m_singletons.begin(), m_singletons.end());
}




//! Access to the global Singleton Manager
SingletonMgr* TC::GlobalSingletonMgr()
{
  static SingletonMgr* TC_VOLATILE smgr = 0;
  if(!smgr)
    smgr = new SingletonMgr;
  TC_POST_CONDITION(smgr);
  return smgr;
}


  //! Access to the Thread-local Singleton Manager
SingletonMgr* TC::ThreadSingletonMgr()
{
  QThreadStorage<SingletonMgr*> tlmgr;

  if(!tlmgr.hasLocalData()) {
    tlmgr.setLocalData(new SingletonMgr);
  }

  return tlmgr.localData();
}

